package com.bsoft.gol.hcs.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsoft.gol.hcs.enumcase.RequestType;
import com.bsoft.gol.hcs.exception.DefineException;
import hcn.util.BaseResponse;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.*;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.nio.charset.CodingErrorAction;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 网络请求
 */
public class HttpClientUtils {
    //默认超时 5s
    public final static int connectTimeout = 300000;
    private final static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    private static final int MAX_TIMEOUT = 3000; //超时时间
    private static final int MAX_TOTAL = 10; //最大连接数
    private static final int ROUTE_MAX_TOTAL = 3; //每个路由基础的连接数
    private static final int MAX_RETRY = 5; //重试次数
    private static PoolingHttpClientConnectionManager connMgr; //连接池
    private static HttpRequestRetryHandler retryHandler; //重试机制

    //    @Value("${invoke_service_type}")
//    private void setInvokeServiceType(String invokeServiceType) {
//        tp = invokeServiceType;
//    }
    private static String tp = "hai";
    private static PoolingHttpClientConnectionManager connManager = null;

    private static CloseableHttpClient httpclient = null;

    static {
        logger.info("123");
        try {
            SSLContext sslContext = SSLContexts.custom().useTLS().build();
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                }
            }}, null);
            Registry<ConnectionSocketFactory> socketFactoryRegistry =
                    RegistryBuilder.<ConnectionSocketFactory>create().register("http",
                            PlainConnectionSocketFactory.INSTANCE).register("https",
                            new SSLConnectionSocketFactory(sslContext)).build();

            connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            httpclient = HttpClients.custom().setConnectionManager(connManager).build();
            // Create socket configuration
            SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
            connManager.setDefaultSocketConfig(socketConfig);
            // Create message constraints
            MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(200).setMaxLineLength(2000).build();
            // Create connection configuration
            ConnectionConfig connectionConfig =
                    ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE).setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8).setMessageConstraints(messageConstraints).build();
            connManager.setDefaultConnectionConfig(connectionConfig);
            connManager.setMaxTotal(200);
            connManager.setDefaultMaxPerRoute(20);
        } catch (KeyManagementException e) {
            logger.error("KeyManagementException", e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException", e);
        }
    }

    public static JSONObject doPost(String url, String serverName, Map<String, String> params) {
        JSONObject res = new JSONObject();
        Date begin = new Date();
        url += serverName;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() == null) {
                params.put(entry.getKey(), "");
            }
        }
        logger.info("url:{}", serverName);
        logger.info("入参:{}", params);
        HttpPost post = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout
                (connectTimeout).setConnectionRequestTimeout(connectTimeout).build();
        post.setConfig(requestConfig);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();

        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }

        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(post);
            try {
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        String str = EntityUtils.toString(entity, "UTF-8");
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        try {
                            res = JSONObject.parseObject(str);
                            logger.info("{}返回值json:{}", serverName, res == null ? null : res.toJSONString());
                        } catch (Exception e) {
                            e.printStackTrace();
                            logger.info("返回值:{}", str);
                        }
                        long l = System.currentTimeMillis() - begin.getTime();
                        if (l > 2000L) {
                            logger.info("接口耗时太长记录：,{}ms,{}", l, serverName);
                        }
                        logger.info("——————————" + simpleDateFormat.format(new Date()) + "(" + serverName + ")耗费时间：" +
                                l + "毫秒——————————");
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            res.put("code", -4);
            res.put("data", "");
            res.put("message", "连接超时");
//			res.put("mesgg","连接超时");
        } finally {
            post.releaseConnection();
        }
        return res == null ? new JSONObject() : res;
    }

    /**
     * @Description:psot请求入参是json字符串
     * @param: [serverName, jsonParams]
     * @return: com.alibaba.fastjson.JSONObject
     * @author:tongtp
     * @Date: 2018/10/8
     */
    public static JSONObject doPostJSONRequest(String url, JSONObject jsonParams) {
        JSONObject res = new JSONObject();
        Date begin = new Date();
//		String url = Constants.HIS_CLIENT_URL+serverName;
//        jsonParams.put("hospitalCode","1");
        logger.info("url:{}", url);
        logger.info("入参:{}", jsonParams);
        HttpPost post = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout
                (connectTimeout)
                .setConnectionRequestTimeout(connectTimeout).build();
        post.setConfig(requestConfig);
        StringEntity requestEntity = null;
        try {
            requestEntity = new StringEntity(jsonParams.toJSONString(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        requestEntity.setContentEncoding("UTF-8");
        post.setHeader("Content-type", "application/json");
        post.setHeader("t", "1");
        post.setEntity(requestEntity);
        try {
            CloseableHttpResponse response = httpclient.execute(post);
            int responseStatusCode = response.getStatusLine().getStatusCode();
            try {
                if (responseStatusCode != 200) {
                    logger.info("responseStatusCode:{}", responseStatusCode);
                    res.put("code", responseStatusCode);
                    res.put("message", "外部接口:" + url + "返回错误");
                    res.put("data", "");
                    return res;
                }
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        String str = EntityUtils.toString(entity, "UTF-8");
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        try {
                            if (CommonUtils.isNotEmpty(str)) {
                                String firstChar = str.substring(0, 1);
                                if ("\"".equals(firstChar)) {
                                    str = str.substring(1, str.length() - 1);
                                }
                                res = JSONObject.parseObject(str);
                            }
                            logger.info("{}返回值json:{}", url, res == null ? null : res.toJSONString());
                        } catch (Exception e) {
                            logger.info("返回值:{}", str);
                            e.printStackTrace();
                        }
                        long l = System.currentTimeMillis() - begin.getTime();
                        if (l > 2000L) {
                            logger.info("接口耗时太长记录：,{}ms,{}", l, url);
                        }
                        logger.info("——————————" + simpleDateFormat.format(new Date()) + "(" + url + ")耗费时间：" +
                                l + "毫秒——————————");
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (ConnectTimeoutException e) {
            res.put("code", -100);
            res.put("data", "");
            res.put("message", "his接口连接超时");
            logger.warn("his接口连接超时");
            return res;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();

        }
        return res == null ? new JSONObject() : res;
    }

    /**
     * @Description:psot请求入参是JSONArray
     * @param: [serverName, jsonParams]
     * @return: com.alibaba.fastjson.JSONObject
     * @author:tongtp
     * @Date: 2018/10/8
     */
    public static JSONObject doPostJSONArrayRequest(String url, JSONArray jsonParams) {
        JSONObject res = new JSONObject();
        Date begin = new Date();
//		String url = Constants.HIS_CLIENT_URL+serverName;
//        jsonParams.put("hospitalCode","1");
        logger.info("url:{}", url);
        logger.info("入参:{}", jsonParams);
        HttpPost post = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout
                (connectTimeout)
                .setConnectionRequestTimeout(connectTimeout).build();
        post.setConfig(requestConfig);
        StringEntity requestEntity = null;
        try {
            requestEntity = new StringEntity(jsonParams.toJSONString(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        requestEntity.setContentEncoding("UTF-8");
        post.setHeader("Content-type", "application/json");
        post.setHeader("t", "1");
        post.setEntity(requestEntity);
        try {
            CloseableHttpResponse response = httpclient.execute(post);
            int responseStatusCode = response.getStatusLine().getStatusCode();
            try {
                if (responseStatusCode != 200) {
                    logger.info("responseStatusCode:{}", responseStatusCode);
                    res.put("code", responseStatusCode);
                    res.put("message", "外部接口:" + url + "返回错误");
                    res.put("data", "");
                    return res;
                }
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        String str = EntityUtils.toString(entity, "UTF-8");
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        try {
                            if (CommonUtils.isNotEmpty(str)) {
                                String firstChar = str.substring(0, 1);
                                if ("\"".equals(firstChar)) {
                                    str = str.substring(1, str.length() - 1);
                                }
                                res = JSONObject.parseObject(str);
                            }
                            logger.info("{}返回值json:{}", url, res == null ? null : res.toJSONString());
                        } catch (Exception e) {
                            logger.info("返回值:{}", str);
                            e.printStackTrace();
                        }
                        long l = System.currentTimeMillis() - begin.getTime();
                        if (l > 2000L) {
                            logger.info("接口耗时太长记录：,{}ms,{}", l, url);
                        }
                        logger.info("——————————" + simpleDateFormat.format(new Date()) + "(" + url + ")耗费时间：" +
                                l + "毫秒——————————");
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (ConnectTimeoutException e) {
            res.put("code", -100);
            res.put("data", "");
            res.put("message", "his接口连接超时");
            logger.warn("his接口连接超时");
            return res;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();

        }
        return res == null ? new JSONObject() : res;
    }

    public static String doPostHbi(String hostUrl, String serviceUrl, String urid, String pwd,
                                   JSONObject requestString) {
        String result = "";

        DataOutputStream out = null;

        BufferedReader reader = null;
        HttpURLConnection connection = null;
        try {
            Date start = new Date();
            String host = hostUrl + "/?";
            StringBuffer sb = new StringBuffer();
            sb.append("clinical.service=" + serviceUrl);
            sb.append("&urid=" + urid);
            sb.append("&pwd=" + pwd);
            sb.append("&parameter=" + URLEncoder.encode(requestString.toJSONString(), "utf-8"));

//			logger.info("平台组装后的url:{}", host+sb.toString());
            URL postUrl = new URL(hostUrl + "/");
            connection = (HttpURLConnection) postUrl.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;Charset=UTF-8");
            connection.connect();
            out = new DataOutputStream(connection.getOutputStream());
            out.writeBytes(sb.toString());
            out.flush();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                result += line;
            }
            System.out.println("结果==============" + result);
            Date end = new Date();
            logger.info("-----调用 HIS 详情 -----\n平台组装后的url: " + host + sb.toString() + "\n入参： " + requestString.toString() + "\n出参: " + result + "\n请求HIS耗时 " + (end.getTime() - start.getTime()) + " 毫秒");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (connection != null) {
                connection.disconnect();
            }

            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return result;

    }

    public static String doPostUrlencoded(String hostUrl, String serviceUrl,
                                   String requestString) {
        String result = "";

        DataOutputStream out = null;

        BufferedReader reader = null;
        HttpURLConnection connection = null;
        try {
            Date start = new Date();
            String host = hostUrl ;
            StringBuffer sb = new StringBuffer();
            sb.append("service=" + serviceUrl);
            sb.append("&urid=" + "");
            sb.append("&pwd=" + "");
//            sb.append("&parameter=" + requestString);
            sb.append("&parameter=" + URLEncoder.encode(requestString, "utf-8"));
//			logger.info("平台组装后的url:{}", host+sb.toString());
            URL postUrl = new URL(hostUrl );
            connection = (HttpURLConnection) postUrl.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;Charset=UTF-8");
            connection.connect();
            out = new DataOutputStream(connection.getOutputStream());
            out.writeBytes(sb.toString());
            out.flush();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                result += line;
            }
            System.out.println("结果==============" + result);
            Date end = new Date();
            logger.info("-----调用 HIS 详情 -----\n平台组装后的url: " + host + sb.toString() + "\n入参： " + requestString.toString() + "\n出参: " + result + "\n请求HIS耗时 " + (end.getTime() - start.getTime()) + " 毫秒");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (connection != null) {
                connection.disconnect();
            }

            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return result;

    }


    public static JSONObject doMainPost(String url, Object... obj) {
        if (obj == null) {
            throw new NullPointerException("参数不能为null");
        }
        if ("".equals(url) || url == null) {
            throw new NullPointerException("url不能为null");
        }
        logger.info("url:{}", url);
        logger.info("入参:{}", JSONObject.toJSONString(obj));

        JSONObject res = null;
        if (Objects.equals(tp, "his")) {
            JSONObject data = (JSONObject) obj[3];
            data.put("hospitalDistId", "A73D49255EC8ECD6069839D354A12B79");
            res = doPostJSONRequest(url + obj[0], data);
        } else {
            JSONObject dataa = (JSONObject) obj[3];
            dataa.put("hospitalDistId", "A73D49255EC8ECD6069839D354A12B79");
//			String data = JSONObject.toJSONString(dataa);
            String str = doPostHbi(url, obj[0].toString(), obj[1].toString(), obj[2].toString(), dataa);
            if (CommonUtils.isNotEmpty(str)) {
                String firstChar = str.substring(0, 1);
                if ("\"".equals(firstChar)) {
                    str = str.substring(1, str.length() - 1);
                }
                res = JSONObject.parseObject(StringEscapeUtils.unescapeJavaScript(str));
            }
        }
        logger.info("出参:{}", res);
        return res == null ? new JSONObject() : res;
    }

    public static String doGet(String url) {
        logger.info("url :" + url);
        String result = "";
        HttpGet get = new HttpGet(url);
        get.addHeader("Content-Type", "text/html;charset=utf-8");
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(500000).build();
        get.setConfig(requestConfig);

        String var7;
        try {
            CloseableHttpResponse httpResponse = httpclient.execute(get);

            try {
                HttpEntity entity = httpResponse.getEntity();

                try {
                    if (entity == null) {
                        return result;
                    }

                    String str = EntityUtils.toString(entity, "UTF-8");
                    logger.info("[HttpUtils Post]response string :" + str);
                    var7 = str;
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }

                }
            } finally {
                if (httpResponse != null) {
                    httpResponse.close();
                }

            }
        } catch (ClientProtocolException var28) {
            var28.printStackTrace();
            result = var28.getMessage().toString();
            return result;
        } catch (IOException var29) {
            var29.printStackTrace();
            result = var29.getMessage().toString();
            return result;
        } finally {
            get.releaseConnection();
        }

        return var7;
    }

    public static String doPost(String url, String json) {
        logger.info("url :" + url + " , param :" + json);
        HttpPost post = new HttpPost(url);
        post.addHeader("Content-Type", "application/json;charset=utf-8");
        StringEntity s;
        try {
            s = new StringEntity(json, "UTF-8");

            post.setEntity(s);

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectTimeout).build();
            post.setConfig(requestConfig);

            long start = System.currentTimeMillis();
            CloseableHttpResponse response = httpclient.execute(post);
            long end = System.currentTimeMillis();
            logger.info("[HttpUtils Post]take time :" + (end - start) + "ms");
            try {
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        String str = EntityUtils.toString(entity, "UTF-8");
                        logger.info("[HttpUtils Post]response string :" + str);
                        return str;
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();
        }
        return "";
    }

    /**
     * @Description:psot请求入参是json字符串
     * @param: [serverName, jsonParams]
     * @return: com.alibaba.fastjson.JSONObject
     * @author:tongtp
     * @Date: 2018/10/8
     */
    public static JSONObject doElectronicPostJSONRequest(String url, JSONObject jsonParams) {
        JSONObject res = new JSONObject();
        Date begin = new Date();
//		String url = Constants.HIS_CLIENT_URL+serverName;
//        jsonParams.put("hospitalCode","1");

        logger.info("url:{}", url);
        logger.info("入参:{}", jsonParams);
        HttpPost post = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout
                (connectTimeout)
                .setConnectionRequestTimeout(connectTimeout).build();
        post.setConfig(requestConfig);
        StringEntity requestEntity = null;
        try {
            requestEntity = new StringEntity(jsonParams.toJSONString(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        requestEntity.setContentEncoding("UTF-8");
        post.setHeader("Content-type", "application/json");
        post.setHeader("requestTag", "1");
        post.setHeader("departmentName", "HIS");
        post.setHeader("organizationId", "1");
        post.setEntity(requestEntity);
        try {
            CloseableHttpResponse response = httpclient.execute(post);
            int responseStatusCode = response.getStatusLine().getStatusCode();
            try {
                if (responseStatusCode != 200) {
                    logger.info("responseStatusCode:{}", responseStatusCode);
                    res.put("code", responseStatusCode);
                    res.put("message", "外部接口:" + url + "返回错误");
                    res.put("data", "");
                    return res;
                }
                HttpEntity entity = response.getEntity();
                try {
                    if (entity != null) {
                        String str = EntityUtils.toString(entity, "UTF-8");
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        try {
                            if (CommonUtils.isNotEmpty(str)) {
                                String firstChar = str.substring(0, 1);
                                if ("\"".equals(firstChar)) {
                                    str = str.substring(1, str.length() - 1);
                                }
                                res = JSONObject.parseObject(StringEscapeUtils.unescapeJavaScript(str));
                            }
                            logger.info("{}返回值json:{}", url, res == null ? null : res.toJSONString());
                        } catch (Exception e) {
                            logger.info("返回值:{}", str);
                            e.printStackTrace();
                        }
                        long l = System.currentTimeMillis() - begin.getTime();
                        if (l > 2000L) {
                            logger.info("接口耗时太长记录：,{}ms,{}", l, url);
                        }
                        logger.info("——————————" + simpleDateFormat.format(new Date()) + "(" + url + ")耗费时间：" +
                                l + "毫秒——————————");
                    }
                } finally {
                    if (entity != null) {
                        entity.getContent().close();
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (ConnectTimeoutException e) {
            res.put("code", -100);
            res.put("data", "");
            res.put("message", "外部接口:" + url + "连接超时");
            logger.warn("外部接口:" + url + "连接超时");
            return res;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();

        }
        return res == null ? new JSONObject() : res;
    }


    /**
     * 发送https请求
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        logger.info("requestUrl {}", requestUrl);
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            conn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            ce.printStackTrace();
            logger.error("连接超时：{}", ce);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("https请求异常Exception：{}", e);
        }
        return jsonObject;
    }

    /**
     * @param reqType {@link RequestType} 请求类型  GET、 POST 、 DELETE 、 PUT
     * @param url     {@link String} 请求目标地址
     * @param headers {@link Map} 请求头
     * @param param   {@link Object} 参数
     * @return
     * @throws DefineException
     * @description 发起HTTP / HTTPS 请求
     * @author 宫清
     * @date 2019年7月11日 上午1:36:12
     */
    public static JSONObject sendHttp(RequestType reqType, String url, Map<String, String> headers, Object param)
            throws DefineException {
        HttpRequestBase reqBase = reqType.getHttpType(url);
        logger.info("\n--->>开始向地址[{}]发起 [{}] 请求", url, reqBase.getMethod());
        logger.info("--->>请求头为{}", JSON.toJSONString(headers));
        long startTime = System.currentTimeMillis();
        CloseableHttpClient httpClient = getHttpClient();
        logger.info("--->>httpClient==={}", httpClient);
        //设置请求url
        config(reqBase);

        //设置请求头
        if (MapUtils.isNotEmpty(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                reqBase.setHeader(entry.getKey(), entry.getValue());
            }
        }

        //添加参数 参数是json字符串
        if (param != null && param instanceof String) {
            String paramStr = String.valueOf(param);
            logger.info("--->>请求参数为：{}", paramStr);
            ((HttpEntityEnclosingRequest) reqBase).setEntity(
                    new StringEntity(String.valueOf(paramStr), ContentType.create("application/json", "UTF-8")));
        }
        //参数时字节流数组
        else if (param != null && param instanceof byte[]) {
            logger.info("--->>请求参数为文件流");
            byte[] paramBytes = (byte[]) param;
            ((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes));
        }


        //响应对象
        CloseableHttpResponse res = null;
        //响应内容
        String resCtx = null;
        try {
            //执行请求
            res = httpClient.execute(reqBase);
            logger.info("--->>执行请求完毕，响应状态：{}", res.getStatusLine());

            if (res.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                throw new DefineException("--->>HTTP访问异常:" + res.getStatusLine());
            }

            //获取请求响应对象和响应entity
            HttpEntity httpEntity = res.getEntity();
            if (httpEntity != null) {
                resCtx = EntityUtils.toString(httpEntity, "utf-8");
                logger.info("--->>获取响应内容：{}", resCtx);
            }

        } catch (Exception e) {
            throw new DefineException("请求失败", e);
        } finally {
            if (res != null) {
                try {
                    res.close();
                } catch (IOException e) {
                    throw new DefineException("--->>关闭请求响应失败", e);
                }
            }
        }
        long endTime = System.currentTimeMillis();
        logger.info("--->>请求执行完毕，耗费时长：{} 秒", (endTime - startTime) / 1000);
        return JSONObject.parseObject(resCtx);
    }

    private static void config(HttpRequestBase httpReqBase) {
        // 配置请求的超时设置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(MAX_TIMEOUT)
                .setConnectTimeout(MAX_TIMEOUT)
                .setSocketTimeout(MAX_TIMEOUT)
                .build();
        httpReqBase.setConfig(requestConfig);
    }

    private static CloseableHttpClient getHttpClient() {
        return HttpClients.custom()
                .setConnectionManager(connMgr)
                .setRetryHandler(retryHandler)
                .build();
    }

    public static JSONObject doGetJson(String httpurl) {
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;// 返回结果字符串
        try {
            logger.info("\n--->>开始向地址{}", httpurl);
            // 创建远程url连接对象
            URL url = new URL(httpurl);
            // 通过远程url连接对象打开一个连接，强转成httpURLConnection类
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接方式：get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间：15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间：60000毫秒
            connection.setReadTimeout(60000);
            // 发送请求
            connection.connect();
            // 通过connection连接，获取输入流
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // 封装输入流is，并指定字符集
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                // 存放数据
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            connection.disconnect();// 关闭远程连接
        }

        return JSONObject.parseObject(result);
    }

    /**
     * 使用apache的HttpClient发送http
     *
     * @param wsdlURL     请求URL
     * @param contentType 如:application/json;charset=utf8
     * @param content     数据内容
     * @DATE 2018年9月22日 下午10:29:17
     */
    static String doHttpPostByHttpClient(String wsdlURL, String contentType, String content)
            throws ClientProtocolException, IOException {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Post请求
        HttpPost httpPost = new HttpPost(wsdlURL);
        StringEntity entity = new StringEntity(content.toString(), "UTF-8");
        // 将数据放入entity中
        httpPost.setEntity(entity);
        httpPost.setHeader("Content-Type", contentType);
        // 响应模型
        CloseableHttpResponse response = null;
        String result = null;
        try {
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            // 注意:和doHttpPostByRestTemplate方法用的不是同一个HttpEntity
            org.apache.http.HttpEntity responseEntity = response.getEntity();

            System.out.println("响应ContentType为:" + responseEntity.getContentType());
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                result = EntityUtils.toString(responseEntity, "UTF-8");
                System.out.println("响应内容为:" + result);
            }
        } finally {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        }
        return result;
    }

    /**
     * @param url
     * @param headerMap
     * @param paramsMap
     * @throws
     * @description: 以Params传参形式发送post请求
     * @return: java.lang.String
     * @author: tongtp
     * @date: 2020/9/18 13:24
     */
    public static BaseResponse postMap(String url, Map<String, String> headerMap, Map<String, String> paramsMap) {
        BaseResponse baseResponse = new BaseResponse();
        String result = "";
        HttpPost post = new HttpPost(url);
        List<NameValuePair> content = new ArrayList<>();
        //参数生成entity
        if (paramsMap != null) {
            for (Map.Entry<String, String> elem :
                    paramsMap.entrySet()) {
                content.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }
        }
        //循环增加header
        if (headerMap != null) {
            for (Map.Entry<String, String> elem :
                    headerMap.entrySet()) {
                content.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }
        }
        if (content.size() > 0) {
            UrlEncodedFormEntity entity = null;
            try {
                entity = new UrlEncodedFormEntity(content, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                logger.error("以Params传参形式发送post请求失败:", e);
                return null;
            }
            post.setEntity(entity);
        }
        //发送请求并接收返回数据
        try (CloseableHttpResponse response = httpclient.execute(post)) {
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                //获取response的body部分
                HttpEntity entity = response.getEntity();
                //读取reponse的body部分并转化成字符串
                result = EntityUtils.toString(entity);
            }
            result.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>","");
            baseResponse.setData(result);
            return baseResponse;
        } catch (UnsupportedEncodingException e) {
            logger.error("以Params传参形式发送post请求失败:", e);
            baseResponse.setCode(-1);
            baseResponse.setMessage(e.getMessage());
            return baseResponse;
        } catch (ClientProtocolException e) {
            logger.error("以Params传参形式发送post请求失败:", e);
            baseResponse.setCode(-2);
            baseResponse.setMessage(e.getMessage());
            return baseResponse;
        } catch (IOException e) {
            logger.error("以Params传参形式发送post请求失败:", e);
            baseResponse.setCode(-3);
            baseResponse.setMessage(e.getMessage());
            return baseResponse;
        }
    }


    public static void main(String[] args) {
        String url = "http://10.8.0.63:8084/labAppointment/app/labAppointment.do?urid=test&service=LabRequestQuery&pwd=bsoft&parameter=";
        String set = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<Bsxml><MsgHeader><Sender>APP</Sender><MsgType>ODS_2101</MsgType><MsgVersion>3.0</MsgVersion></MsgHeader><Visit><MedicalCardType>1</MedicalCardType><VisitOrganization>330108001</VisitOrganization><MedicalCardId>00000137</MedicalCardId><Hosarea>1256</Hosarea><QueryType>1</QueryType></Visit><LabRequest><EffectiveTimeLow>20200921T000000</EffectiveTimeLow>" +
                "<IsAppointment>1</IsAppointment><EffectiveTimeHigh>20200925T235959</EffectiveTimeHigh></LabRequest></Bsxml>";
        String encode = null;
        try {
            encode = URLEncoder.encode(set, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        String result = null;
        try {
            result = HttpClientUtils.doGet(url + encode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (result == null) {
            //失败
        } else {
            //成功
            System.out.println(result);
        }
    }


}

